﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using AesonBaseFramework.Annotations;
using AesonBaseFramework.EntityFramework.Repositories.Interfaces;
using System.Data.Entity;

namespace AesonBaseFramework.EntityFramework.Repositories.BaseRepositories
{
    public class BaseSqlRepository<T> : IBaseAsyncRepository<T> where T : class 
    {
        protected DbContext Ctx;
        public BaseSqlRepository([NotNull] DbContext context)
        {
            if (context == null) throw new ArgumentNullException("context");
            Ctx = context;
        }

        public async Task<ICollection<T>> GetAllAsync()
        {
            return await Ctx.Set<T>().ToListAsync();
        }
        public IQueryable<T> GetAllQueryable()
        {
            return Ctx.Set<T>().AsQueryable<T>();
        }

        public ICollection<T> GetALll()
        {
            return Ctx.Set<T>().ToList();
        }

        public async Task<T> GetByIdAsync(int id)
        {
            return await Ctx.Set<T>().FindAsync(id);
        }

        public async Task<T> GetSingleAsync(Expression<Func<T, bool>> match)
        {
            return await Ctx.Set<T>().SingleOrDefaultAsync(match);
        }

        public async Task<ICollection<T>> GetAllAsyncWhere(Expression<Func<T, bool>> match)
        {
            return await Ctx.Set<T>().Where(match).ToListAsync();
        }

        public T Add(T toBeAddes)
        {
            return Ctx.Set<T>().Add(toBeAddes);
        }

        public async Task<T> UpdateAsync(T updated, int key)
        {

            if (updated == null)
                return null;

            T existing = await Ctx.Set<T>().FindAsync(key);
            if (existing != null)
            {
                Ctx.Entry(existing).CurrentValues.SetValues(updated);
            }
            return existing;
        }

        public T Remove(T toBeRemoved)
        {
            return Ctx.Set<T>().Remove(toBeRemoved);
        }


        public async Task<int> CountAsync()
        {
            return await Ctx.Set<T>().CountAsync();
        }

    }
}
